﻿using SharpSoft.WPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace SharpSoft.WPF
{
    /// <summary>
    /// 树节点扩展
    /// </summary>
    public class TreeViewItemExtension
    {


        public static bool GetIsScrolledToViewWhenSelected(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsScrolledToViewWhenSelectedProperty);
        }

        public static void SetIsScrolledToViewWhenSelected(DependencyObject obj, bool value)
        {
            obj.SetValue(IsScrolledToViewWhenSelectedProperty, value);
        }


        public static readonly DependencyProperty IsScrolledToViewWhenSelectedProperty =
            DependencyProperty.RegisterAttached("IsScrolledToViewWhenSelected", typeof(bool), typeof(TreeViewItemExtension), new PropertyMetadata(default(bool), new PropertyChangedCallback(OnIsScrolledToViewWhenSelectedChanged)));



        public static bool GetHasSetSelectedItemVisible(DependencyObject obj)
        {
            return (bool)obj.GetValue(HasSetSelectedItemVisibleProperty);
        }

        public static void SetHasSetSelectedItemVisible(DependencyObject obj, bool value)
        {
            obj.SetValue(HasSetSelectedItemVisibleProperty, value);
        }

        // Using a DependencyProperty as the backing store for HasSetSelectedItemVisible.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HasSetSelectedItemVisibleProperty =
            DependencyProperty.RegisterAttached("HasSetSelectedItemVisible", typeof(bool), typeof(TreeViewItemExtension), new PropertyMetadata(default(bool)));




        static void OnIsScrolledToViewWhenSelectedChanged(
           DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {
            if (depObj is TreeViewItem treeViewItem && e.NewValue is bool isIntoViewWhenSelected)
            {
                treeViewItem.Loaded -= TreeViewItem_Loaded;
                //获取父控件TreeView
                var treeView = VisualHelper.FindParent<TreeView>(treeViewItem);
                if (isIntoViewWhenSelected)
                {
                    //开启了虚拟化且未完成滚动，直接返回
                    var isOpeningVitualizing = ScrollViewer.GetCanContentScroll(treeView) && VirtualizingPanel.GetIsVirtualizing(treeView);
                    if (isOpeningVitualizing && GetHasSetSelectedItemVisible(treeView))
                    {
                        return;
                    }
                    treeViewItem.Loaded += TreeViewItem_Loaded;
                }
            }
        }

        private static void TreeViewItem_Loaded(object sender, RoutedEventArgs e)
        {
            var treeViewItem = e.OriginalSource as TreeViewItem;
            if (treeViewItem != null)
            {
                treeViewItem.Loaded -= TreeViewItem_Loaded;
                //获取父控件TreeView
                var treeView = VisualHelper.FindParent<TreeView>(treeViewItem);
                //是否开启了虚拟化
                var isOpeningVirtualizing = ScrollViewer.GetCanContentScroll(treeView) && VirtualizingPanel.GetIsVirtualizing(treeView);
                if (isOpeningVirtualizing)
                {
                    if (treeViewItem.IsSelected)
                    {
                        //设置已完成滚动，减少剩余项的加载判断
                        SetHasSetSelectedItemVisible(treeView, true);
                        treeViewItem.BringIntoView();
                    }
                    else
                    {
                        treeViewItem.BringIntoView();
                    }
                }
                else if (treeViewItem.IsSelected)
                {
                    treeViewItem.BringIntoView();
                }
                else
                {
                    var dc = treeViewItem.DataContext;
                    if (dc != null)
                    {
                        var t = dc.GetType();
                        var p = t.GetProperty("IsSelected", System.Reflection.BindingFlags.Instance| System.Reflection.BindingFlags.Public);
                        var issel = (bool)p.GetValue(dc);
                        if (issel)
                        {
                            treeViewItem.BringIntoView();
                        }
                    }
                }
            }
        }
    }
}
